package pl.pyjter;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.JoinColumn;

@SuppressWarnings("deprecation")
public class LibraryHibImpl {
	private final static SessionFactory factory;
	static {
		factory = new Configuration().configure().buildSessionFactory();
	}
	
	public static LinkedHashMap<String, Method> sortMap(LinkedHashMap<String, Method> map, String[] order) {
		LinkedHashMap<String, Method> elementsMap = new LinkedHashMap<>();
		
		for(String key : order) {
			elementsMap.put(key, map.get(key));
		}
		
		return elementsMap;
	}
	
	public static <T> LinkedHashMap<String, Method> getElements(Class<T> cls) throws Throwable {
		LinkedHashMap<String, Method> elementsMap = new LinkedHashMap<>();
		
		for(Method method : cls.getDeclaredMethods()) {
			Column col = method.getAnnotation(Column.class);
			if(col != null) {
				elementsMap.put(col.name(), method);
			}
		}		
		String[] order = (String[]) (cls.getMethod("getColumnsOrder")).invoke(cls);
		return sortMap(elementsMap, order);
	}
	
	public static <T> LinkedHashMap<Class, Method> getJoindedClasses(Class<T> cls) {
		LinkedHashMap<Class, Method> joinedClassesMap = new LinkedHashMap<>();

		for(Method method : cls.getDeclaredMethods()) {
			JoinColumn col = method.getAnnotation(JoinColumn.class);
			if(col != null) {
				joinedClassesMap.put(method.getReturnType(), method);
			}
		}		
		
		return joinedClassesMap;
	}
	
	public <T> List<T> getObjects(String name) {
		Session session = factory.openSession();
		@SuppressWarnings("unchecked")
		List<T> ObjectList = session.createQuery("from " + name).list();
		session.close();
		return ObjectList;
	}
	
	public <T> T getObject(Class<T> cls, int id) {
		Session session = factory.openSession();
		@SuppressWarnings("unchecked")
		T object = (T)session.get(cls, id);
		session.close();
		return object;
	}

	public <T> void insertObject(T object) {
		Session session = factory.openSession();
		Transaction tx = session.beginTransaction();
		session.persist(object);
		tx.commit();
		session.close();
	}
	
	public <T> void updateObject(T object) {
		Session session = factory.openSession();
		Transaction tx = session.beginTransaction();
		session.saveOrUpdate(object);
		tx.commit();
		session.close();
	}
	
	public <T> void deleteObject(T object) {
		Session session = factory.openSession();
		Transaction tx = session.beginTransaction();
		session.delete(object);
		tx.commit();
		session.close();
	}	
	
	public <T> void deleteObject(Class<T> cls, int id) {
		Session session = factory.openSession();
		Transaction tx = session.beginTransaction();
		@SuppressWarnings("unchecked")
		T object = (T)session.get(cls, id);		
		session.delete(object);
		tx.commit();
		session.close();
	}
}
